import java.util.SortedSet;
import java.util.TreeSet;
import data.ClusteredNode;
import data.GeneDataFile;
import java.io.File;

import utils.CalculatorFactory;
import utils.ClusterDistanceCalculator;

public class Cluster {

	private GeneDataFile dataFile;
	private ClusterDistanceCalculator calculator;
	private int numberOfCluster;
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		if (args.length<3) {
			System.out.println("Required params: dataFileName distanceCalculatorType numberOfClusters");
			return;
		}
		
		CalculatorFactory.reset();
		Cluster cluster = new Cluster();
		if (!cluster.setDataFile(args[0])) {
			System.out.println("Fail to get genes data file: '"+args[0]+"'");
			return;
		}
		if (!cluster.setDistanceCalcuationMethod(args[1])) {
			System.out.println("Fail to get distance calculator: '"+args[1]+"'");
			return;
		}
		if (!cluster.setNumberOfCluster(Integer.valueOf(args[2]).intValue())) {
			System.out.println("Fail to set number of clusters: '"+args[2]+"'");
			return;
		}
		
		cluster.run();
		System.exit(0);
	}
	
	public Cluster() {
		
	}
	
	public boolean setDistanceCalcuationMethod(String clusterDistance) {
		return setDistanceCalcuationMethod(clusterDistance, CalculatorFactory.EUCLIDEAN );
		
	}
	
	public boolean setDistanceCalcuationMethod(String clusterDistance, String geneDistance) {
		calculator = CalculatorFactory.getClusterDistanceCalculator(clusterDistance, geneDistance);
		return (calculator!=null);
	}
	
	public boolean setDataFile(String filePath) {
		File file=new File(filePath);
		if (file.canRead()) {
			try {
				dataFile = new GeneDataFile(file);				
			} catch (Exception e) {
				e.printStackTrace();
				return false;
			}
			return true;
		}
		return false;
	}
	
	public boolean setNumberOfCluster(int k){
		numberOfCluster=k;
		return (numberOfCluster>0);
	}
	
	private void run() {
		Clustor clustor = new Clustor();
		clustor.setGenes(dataFile.genes());
		clustor.setCalculator(calculator);
		clustor.setNumberOfClusters(numberOfCluster);
		SortedSet<ClusteredNode> clusters = new TreeSet<ClusteredNode>( clustor.getClusters());
		
		for (ClusteredNode c:clusters) {
			System.out.println( c.toString()+Math.round(c.getClusterAverage()*1000.0)/1000.0+"\n");
		}		
	}
}
